#!/bin/bash
#--------------------------------------------------------------------
# Script to use osc command line to populate a new OpenHPC minor
# branch in OBS from a previous version.
#
# Originally: 9/7/2016 - karl.w.schulz@intel.com
#--------------------------------------------------------------------

if [ "$#" -lt 2 ];then
    echo "usage: `basename $0` [source-project] [target-project] <optional pkg-name>"
    exit 1
fi

export branchCurrent=$1
export branchNew=$2


ENABLE_CMDS=1
DISABLE_ARCH="x86_64 aarch64"
SKIP_LINK_UPDATES="latexmk"
SKIP_SERVICE_UPDATES="XXXXXXX"

MAX_UPDATES=2   # 1.3.2 was last 1.1 release
#MAX_UPDATES=0   # 1.3.2 was last 1.3 release (set to 0 when creating from previous update release)

TMPDIR=$(mktemp -d) || exit 1

ERROR () {

    echo "[ERROR]: $1" >&2
    exit 1
}


run_cmd () {
    local cmd="$@"

    if [[ ${ENABLE_CMDS} -eq 0 ]];then
	echo "   [would have run]: $cmd"
    else
	echo "running $cmd"
	eval $cmd
    fi
}

query_minor_branch () {
    export SOURCE_VER=`echo $1 | awk -F : '{print $2}'`
    [[ -z "${SOURCE_VER}" ]] && { echo "Error querying minor branch for $1"; exit 1; }

    export PARENT_PROJ=`echo $1 | awk -F : '{print $1}'`
    [[ -z "${PARENT_PROJ}" ]] && { echo "Error querying project name for $1"; exit 1; }
}

check_for_package_update () {
    found_update=""
    found_link=0
    parent_path=${branchCurrent}

    local igot

    # before scanning for updates, check if this is a child package with _link
    osc api -X GET "/source/${branchCurrent}/$1/_link" &> /dev/null && found_link=1 || found_link=0

    for i in `seq 1 ${MAX_UPDATES}`; do 

	igot=$(osc ls ${PARENT_PROJ}:${SOURCE_VER}:Update$i:Factory $1 2> /dev/null)
	returned=$?

	if [ $returned -eq 0 ];then

	    if [ "${igot}" == "_aggregate" ];then
		echo "Ignoring _aggregate package..."
		continue
	    fi

	    # check if this a child package with _link
	    osc api -X GET "/source/${PARENT_PROJ}:${SOURCE_VER}:Update$i:Factory/$1/_link" &> /dev/null && found_link=1 || found_link=0

	    parent_path="${PARENT_PROJ}:${SOURCE_VER}:Update$i:Factory"
	    found_update=$i
	fi
    done
}

update_pkg_if_link () {

    local localdir="${branchNew}/$1"

    cd $TMPDIR || ERROR "unable to cd to $TMPDIR"
    osc co ${branchNew} $1

    osc api -X GET "/source/${parent_path}/$1/_link" > ${localdir}/_link || ERROR "unable to copy _link from ${parent_path}"

    osc add ${localdir}/_link || ERROR "Unable to add _link file for $1"
    if [ -e ${localdir}/_service ];then
	osc rm ${localdir}/_service || ERROR "Unable to remove _service file for $1"
    fi

    # update the _link to the new branch (unless in SKIP list)

    echo "${SKIP_LINK_UPDATES}" | grep -q $1
    if [ $? -eq 1 ];then
	perl -pi -e 's/project=\'\S+\'/project=\'${branchNew}\'/ ${localdir}/_link || ERROR "unable to update parent in _link for $1"
    fi

    # update to latest gnu compiler family
    gnu_family=gnu7

    echo $1 | grep -q gnu
    if [ $? -eq 0 ];then
	echo "Updating _link for gnu compiler family"
	perl -pi -e "s/compiler_family gnu</compiler_family ${gnu_family}</" ${localdir}/_link
    fi

    cd -
} # end update_pkg_if_link()

update_pkg_if_service () {

    local localdir="${branchNew}/$1"
    local version=`echo $branchNew | awk -F : '{print $2}'`

    echo "${branchNew}" | grep -q ":Update" 

    if [ $? -eq 0 ];then
	local update_ver=`echo $branchNew | awk -F : '{print $3}' | awk -F 'Update' '{print $2}'`
	version="$version.$update_ver"
    fi

    local revision="obs/OpenHPC_${version}_Factory"

    echo "--> _service file: revision = $revision"

    cd $TMPDIR || ERROR "unable to cd to $TMPDIR"
    osc co ${branchNew} $1

    # update the _service to the new branch (unless in SKIP list)

    echo "${SKIP_SERVICE_UPDATES}" | grep -q $1
    if [ $? -eq 1 ];then
	perl -i -pe "s!revision\">(\S+)<!revision\">$revision<!"  ${localdir}/_service || ERROR "unable to update revision in _service for $1"
    fi

    osc ci ${localdir} -m "committing updated _service file for $1"

    cd -
}

echo " "
echo "Using source branch = $branchCurrent"
query_minor_branch $branchCurrent
echo "Minor version branch (source) = ${SOURCE_VER}"
echo "Parent project                = ${PARENT_PROJ}"
echo "TMPDIR                        = $TMPDIR"
echo " "

if [ $# -gt 2 ];then
    PKG_LIST=$3
else
    PKG_LIST=`osc ls ${branchCurrent}`
fi

for PKG in ${PKG_LIST} ; do 

    echo "Copying existing package $PKG from ${branchCurrent} to ${branchNew}..."

    if [[ ${PKG} == "_pattern" ]];then
	echo "Skipping _pattern..."
	continue
    fi
    
    # check for package in update releases...
    check_for_package_update ${PKG}

    if [[ -n ${found_update} ]];then
	echo "Update found for ${PKG} -> Update${found_update}"
	cmd="osc release ${PARENT_PROJ}:${SOURCE_VER}:Update${found_update}:Factory $PKG"
    else
	cmd="osc release ${branchCurrent} $PKG"
    fi
    
    run_cmd "$cmd"

    # disable arch'es present in previous build (to avoid rebuilds)
    # osc api -X POST "/source/OpenHPC:1.2:Factory/autoconf?cmd=set_flag&flag=build&status=disable&arch=x86_64"

    for myarch in ${DISABLE_ARCH}; do    
	cmd="osc api -X POST \"/source/${branchNew}/${PKG}?cmd=set_flag&flag=build&status=disable&arch=${myarch}\""
	run_cmd "$cmd"
    done

    # Update path in _service files to match new release branch

    if [[ ($found_link -eq 0) && ($ENABLE_CMDS -eq 1) ]]; then
	echo "Upating _service file to use latest branch for source"
	update_pkg_if_service ${PKG} 
    fi
    
    # update config if source_package was a link, since "osc release" will simply create a _service file
    if [[ ($found_link -eq 1) && ($ENABLE_CMDS -eq 1) ]]; then
	echo "Originating package source for $PKG is a _link..."
	update_pkg_if_link ${PKG}
    fi
    
    
done

if [[ $found_link -eq 1 ]];then
    echo " "
    echo "At least 1 _link file updated. committing staged changes in $TMPDIR..."
    if [ $# -gt 2 ];then
	cd $TMPDIR/$branchNew/$3
    else
	cd $TMPDIR
    fi
    osc ci -m "committing updated _link files"
    cd -
fi
